package com.eastmoney.emis.edda.task.eddi.processor;

import com.eastmoney.emis.edda.config.HsbcEddaConfig;
import com.eastmoney.emis.edda.domain.entity.EddiInstruction;
import com.eastmoney.emis.edda.domain.event.EddiInstructionEvent;
import com.eastmoney.emis.edda.domain.event.EventPublisher;
import com.eastmoney.emis.edda.domain.repository.HsbcEddiRepository;
import com.eastmoney.emis.edda.domain.service.IdService;
import com.eastmoney.emis.edda.domain.valueobject.EddiOperation;
import com.eastmoney.emis.edda.domain.valueobject.EddiStatus;
import com.eastmoney.emis.edda.infrastructure.fund.FundDepositProvider;
import com.eastmoney.emis.edda.infrastructure.fund.FundDepositReq;
import com.eastmoney.emis.edda.infrastructure.fund.FundDepositStatus;
import com.eastmoney.emis.edda.infrastructure.fund.FundRes;
import com.eastmoney.emis.edda.task.eddi.EddiTask;
import com.eastmoney.emis.logger.LoggerFactory;
import com.eastmoney.emis.utils.common.po.BaseResponse;
import com.eastmoney.emis.utils.common.utils.JSONUtils;
import org.slf4j.Logger;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Component;

import java.time.LocalDateTime;

/**
 * @description: Description
 * @projectName: EDDA-HSBC
 * @package: com.eastmoney.emis.edda.task.eddi
 * @author: 汪程程
 * @date: 2022/10/13 2:27 PM
 * @version: 1.0
 */
@Order(5)
@Component
public class EddiFundDepositFailProcessor implements EddiProcessor {

    private static Logger log = LoggerFactory.getLogger(EddiFundDepositFailProcessor.class);
    @Autowired
    private HsbcEddiRepository eddiRepository;
    @Autowired
    private EventPublisher eventPublisher;
    @Autowired
    private FundDepositProvider fundDepositProvider;
    @Autowired
    private HsbcEddaConfig config;
    @Autowired
    private IdService idService;

    @Override
    public boolean canProcess(String status) {
        return EddiStatus.FUND_DEPOSIT_FAIL.value().equals(status);
    }

    @Override
    public void execute(EddiTask task) {
        EddiInstruction eddiInstruction = task.getEddiInstruction();
        FundDepositReq fundDepositReq = new FundDepositReq(eddiInstruction);
        fundDepositReq.setBankId(config.getDepositBankId());
        fundDepositReq.setBankAccount(config.getDepositBankAccount());
        fundDepositReq.setRequestId(idService.generateId());
        BaseResponse<FundRes> response = fundDepositProvider.fundDeposit(fundDepositReq);
        FundDepositStatus fundDepositStatus = FundDepositStatus.parse(response.getStatus());
        if (fundDepositStatus == FundDepositStatus.SUCCESS) {
            eddiInstruction.finish(response.getData().getSerialNo());
        } else {
            log.warn("fund deposit fail, code = {}, message = {}, eid = {}", response.getStatus(), response.getMessage(), eddiInstruction.getEid());
        }
        eddiRepository.saveDebitInstruction(eddiInstruction);
        publishEvent(eddiInstruction, fundDepositReq, response);

        if(fundDepositStatus == FundDepositStatus.VALUE_DATE_EARLY_OPEN_ACCOUNT) {
            retryFundDeposit(fundDepositReq, eddiInstruction);
        }

    }

    private void retryFundDeposit(FundDepositReq fundDepositReq, EddiInstruction eddiInstruction) {
        fundDepositReq.setValueDate("");
        fundDepositReq.setRequestId(idService.generateId());
        BaseResponse<FundRes> retryResponse = fundDepositProvider.fundDeposit(fundDepositReq);
        FundDepositStatus retryFundDepositStatus = FundDepositStatus.parse(retryResponse.getStatus());
        if (retryFundDepositStatus == FundDepositStatus.SUCCESS) {
            eddiInstruction.finish(retryResponse.getData().getSerialNo());
        } else {
            log.warn("fund deposit fail, code = {}, message = {}, eid = {}", retryResponse.getStatus(), retryResponse.getMessage(), eddiInstruction.getEid());
        }
        eddiRepository.saveDebitInstruction(eddiInstruction);
        publishEvent(eddiInstruction, fundDepositReq, retryResponse);
    }


    private void publishEvent(EddiInstruction eddiInstruction, FundDepositReq fundDepositReq, BaseResponse resp) {
        EddiInstructionEvent event = new EddiInstructionEvent(eddiInstruction);
        event.setResult(resp.getMessage());
        event.setOperation(EddiOperation.FUND_DEPOSIT.getValue());
        if (resp.getStatus() != 0) {
            event.setErrorReason(resp.getMessage());
            event.setErrorNo(Integer.toString(resp.getStatus()));
        }
        event.setApplyReq(JSONUtils.toJSONString(fundDepositReq));
        event.setApplyRes(JSONUtils.toJSONString(resp));
        eventPublisher.publish(event);
    }

}
